import time
import json
from os import path
from flask import(
    Blueprint,
    send_from_directory,
    current_app,
    flash,
    redirect,
    render_template,
    request,
    url_for
)
from flask_jwt_extended import jwt_required, get_jwt_identity
from flask_login import login_user
from flask_wtf import FlaskForm
from wtforms import (
    StringField, 
    SelectField,
    FileField,
    SubmitField,
)
from wtforms.validators import (
    DataRequired, 
    ValidationError
)
from werkzeug.utils import secure_filename

from app import db


web_bp = Blueprint('web', __name__, url_prefix='/web')


class UserInfoForm(FlaskForm):
    nickname = StringField('昵称', validators=[DataRequired()])
    gender = SelectField('性别', choices=[('male', '男'), ('female', '女')], validators=[DataRequired()])
    country = SelectField('国家', choices=[('China', '中国'), ('USA', '美国'), ('Japan', '日本')], validators=[DataRequired()])
    email = StringField('邮箱', validators=[DataRequired()])
    bro = StringField('简介', default='')
    avatar = FileField('头像')
    SubmitField = SubmitField('保存')
    
    def validata_avatar(self,field):
        if not field.data:
            raise ValidationError('请选择文件')
        
        file_name = field.data.filename.lower() # 文件名转为小写
        valid_extensions = {'jpg', 'jpeg', 'png'}
        #1 检查文件扩展名
        if not path.splitext(file_name)[1][1:] in valid_extensions:
            raise ValidationError('请上传图片文件')

        #2 检查MIME类型（防止伪造扩展名）
        mime_type = field.data.content_type.lower()
        valid_mimes = {'image/jpeg', 'image/png'}
        if mime_type not in valid_mimes:
            raise ValidationError('请上传真实图片文件')

        #3 检查文件大小
        if field.data.content_length > current_app.config['MAX_CONTENT_LENGTH']:
            raise ValidationError(f'图片文件超过3MB')

def searchUserInfo(id):
    from app import redis_client
    cache_key = f'user:{id}'

    if redis_client.exists(cache_key):
        userInfo = json.loads(redis_client.get(cache_key))
        # print(userInfo)
        return userInfo 
    else:
        from app.models import UserInfo, UserInfoSchema

        user_info_schema = UserInfoSchema()
        userInfo = UserInfo.query.filter_by(id=id).first()

        info_data_dict = user_info_schema.dump(userInfo)
        info_data_json = json.dumps(info_data_dict)

        redis_client.setex(cache_key, 3600, info_data_json)

        return info_data_dict

@web_bp.route('/')
@jwt_required()
def index():
    """首页"""
    return render_template(
        'web/index.html',
        tab=request.args.get('tab', 'chatroom')
    )

@web_bp.route('/profile')
@jwt_required()
def profile():
    current_user_id = get_jwt_identity()
    userInfo = searchUserInfo(current_user_id)
    return render_template('web/profile.html', UserInfo = userInfo)

@web_bp.route('/edit_profile', methods=['GET', 'POST'])
@jwt_required()
def edit_profile():
    form = UserInfoForm()
    current_user_id = get_jwt_identity() # 通过符合token字段获取用户id
    if request.method == 'POST':
        if form.validate_on_submit():
            print('修改个人信息ing')
            newInfo = {}
            for field in ['nickname', 'gender', 'country', 'email', 'bro']:
                newInfo[field] = request.form[field]
                
            avatar = request.files['avatar']
            if avatar:
                filename = secure_filename(avatar.filename)
                # 生成本地保存的固定格式名
                extension = path.splitext(filename)[1]
                save_filename = str(round(time.time() * 1000)) + extension
                
                newInfo['avatar'] = save_filename
                # 本地保存目录
                save_dir = path.join(current_app.root_path, 'media', 'images')

                # 文件保存地址
                file_path = path.join(save_dir, save_filename)

                # 保存文件
                avatar.save(file_path)



            db.session.query(UserInfo).filter(UserInfo.id == current_user_id).update(newInfo)
            db.session.commit()

            userInfo = db.session.query(UserInfo).filter(UserInfo.id == current_user_id).first()
            # 更新Redis缓存
            redis_client.delete(f'user:{current_user_id}')
            redis_client.setex(f'user:{user_id}', 3600, json.dumps(userInfo))
            flash('保存成功')
            return redirect(url_for('web.profile'))
        else:
            print('表单信息不符合规范')
            print(form.csrf_token.current_token)
            return render_template('web/edit_profile.html', form = form)

    return render_template('web/edit_profile.html', form = form)

@web_bp.route('/media/images/<path:filename>')
def media_images(filename):
    ### 访问media下的文件 ###
    print(filename)
    return send_from_directory('media/images', filename)
